/*     */ package com.zimbra.qa.unittest;
/*     */ 
/*     */ import com.google.common.collect.Lists;
/*     */ import com.zimbra.client.ZFolder;
/*     */ import com.zimbra.client.ZFolder.Color;
/*     */ import com.zimbra.client.ZFolder.View;
/*     */ import com.zimbra.client.ZMailbox;
/*     */ import com.zimbra.client.ZTag;
/*     */ import com.zimbra.client.ZTag.Color;
/*     */ import com.zimbra.common.localconfig.KnownKey;
/*     */ import com.zimbra.common.localconfig.LC;
/*     */ import com.zimbra.common.service.ServiceException;
/*     */ import com.zimbra.common.util.AccessBoundedRegex;
/*     */ import com.zimbra.common.util.AccessBoundedRegex.TooManyAccessesToMatchTargetException;
/*     */ import com.zimbra.common.util.Log;
/*     */ import com.zimbra.common.util.Log.Level;
/*     */ import com.zimbra.common.util.ZimbraLog;
/*     */ import com.zimbra.cs.mailclient.CommandFailedException;
/*     */ import com.zimbra.cs.mailclient.MailConfig;
/*     */ import com.zimbra.cs.mailclient.imap.AppendMessage;
/*     */ import com.zimbra.cs.mailclient.imap.AppendResult;
/*     */ import com.zimbra.cs.mailclient.imap.Body;
/*     */ import com.zimbra.cs.mailclient.imap.CAtom;
/*     */ import com.zimbra.cs.mailclient.imap.Flags;
/*     */ import com.zimbra.cs.mailclient.imap.ImapConfig;
/*     */ import com.zimbra.cs.mailclient.imap.ImapConnection;
/*     */ import com.zimbra.cs.mailclient.imap.ImapData;
/*     */ import com.zimbra.cs.mailclient.imap.ImapRequest;
/*     */ import com.zimbra.cs.mailclient.imap.ImapResponse;
/*     */ import com.zimbra.cs.mailclient.imap.ListData;
/*     */ import com.zimbra.cs.mailclient.imap.Literal;
/*     */ import com.zimbra.cs.mailclient.imap.MailboxInfo;
/*     */ import com.zimbra.cs.mailclient.imap.MailboxName;
/*     */ import com.zimbra.cs.mailclient.imap.MessageData;
/*     */ import com.zimbra.cs.mailclient.imap.ResponseHandler;
/*     */ import java.io.File;
/*     */ import java.io.FileWriter;
/*     */ import java.io.IOException;
/*     */ import java.io.UnsupportedEncodingException;
/*     */ import java.sql.Date;
/*     */ import java.util.Iterator;
/*     */ import java.util.List;
/*     */ import java.util.Map;
/*     */ import java.util.Set;
/*     */ import java.util.regex.Pattern;
/*     */ import junit.framework.TestCase;
/*     */ import org.apache.commons.lang.StringUtils;
/*     */ import org.junit.Test;
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ 
/*     */ public class TestImap
/*     */   extends TestCase
/*     */ {
/*     */   private static final String HOST = "localhost";
/*     */   private static final int PORT = 7143;
/*     */   private static final String USER = "imap-test-user";
/*     */   private static final String PASS = "test123";
/*     */   private ImapConnection connection;
/*     */   
/*     */   public void setUp()
/*     */     throws Exception
/*     */   {
/*  79 */     if (!TestUtil.fromRunUnitTests) {
/*  80 */       TestUtil.cliSetup();
/*     */     }
/*  82 */     TestUtil.deleteAccount("imap-test-user");
/*  83 */     TestUtil.createAccount("imap-test-user");
/*  84 */     this.connection = connect();
/*     */   }
/*     */   
/*     */   public void tearDown() throws Exception
/*     */   {
/*  89 */     ZMailbox mbox = TestUtil.getZMailbox("imap-test-user");
/*     */     
/*  91 */     if (this.connection != null) {
/*  92 */       this.connection.close();
/*     */     }
/*  94 */     TestUtil.deleteAccount("imap-test-user");
/*     */   }
/*     */   
/*     */   private void checkRegex(String regexPatt, String target, Boolean expected, int maxAccesses, Boolean timeoutOk) {
/*     */     try {
/*  99 */       Pattern patt = Pattern.compile(regexPatt);
/* 100 */       AccessBoundedRegex re = new AccessBoundedRegex(patt, maxAccesses);
/* 101 */       assertEquals(String.format("matching '%s' against pattern '%s'", new Object[] { target, patt }), expected, new Boolean(re.matches(target)));
/*     */     }
/*     */     catch (AccessBoundedRegex.TooManyAccessesToMatchTargetException se) {
/* 104 */       assertTrue("Throwing exception considered OK", timeoutOk.booleanValue());
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testSubClauseAndSearch() throws IOException {
/* 110 */     this.connection.select("INBOX");
/* 111 */     this.connection.search((Object[])new String[] { "OR (FROM yahoo.com) (FROM hotmail.com)" });
/* 112 */     this.connection.search((Object[])new String[] { "(SEEN)" });
/* 113 */     this.connection.search((Object[])new String[] { "(SEEN (ANSWERED UNDELETED))" });
/* 114 */     this.connection.search((Object[])new String[] { "NOT (SEEN UNDELETED)" });
/* 115 */     this.connection.search((Object[])new String[] { "(SEEN UNDELETED)" });
/* 116 */     this.connection.search((Object[])new String[] { "OR ANSWERED (SEEN UNDELETED)" });
/* 117 */     this.connection.search((Object[])new String[] { "OR (SEEN UNDELETED) ANSWERED" });
/* 118 */     this.connection.search((Object[])new String[] { "OR ((SEEN UNDELETED) ANSWERED) DRAFT" });
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testNotSearch() throws IOException {
/* 123 */     this.connection.select("INBOX");
/* 124 */     this.connection.search((Object[])new String[] { "NOT SEEN" });
/* 125 */     this.connection.search((Object[])new String[] { "NOT NOT SEEN" });
/* 126 */     this.connection.search((Object[])new String[] { "NOT NOT NOT SEEN" });
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testAndSearch() throws IOException {
/* 131 */     this.connection.select("INBOX");
/* 132 */     this.connection.search((Object[])new String[] { "HEADER Message-ID z@eg" });
/* 133 */     this.connection.search((Object[])new String[] { "HEADER Message-ID z@eg UNDELETED" });
/* 134 */     this.connection.search((Object[])new String[] { "ANSWERED HEADER Message-ID z@eg UNDELETED" });
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testBadOrSearch() throws IOException {
/* 139 */     this.connection.select("INBOX");
/*     */     try {
/* 141 */       this.connection.search((Object[])new String[] { "OR ANSWERED" });
/* 142 */       org.junit.Assert.fail("search succeeded in spite of invalid syntax");
/*     */     } catch (CommandFailedException cfe) {
/* 144 */       ZimbraLog.test.debug("Got this exception", cfe);
/* 145 */       String es = "SEARCH failed: parse error: unexpected end of line; expected ' '";
/* 146 */       org.junit.Assert.assertTrue(String.format("Exception '%s' should contain string '%s'", new Object[] { cfe.getMessage(), es }), cfe.getMessage().contains(es));
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testOrSearch() throws IOException
/*     */   {
/* 153 */     this.connection.select("INBOX");
/* 154 */     this.connection.search((Object[])new String[] { "OR SEEN ANSWERED DELETED" });
/* 155 */     this.connection.search((Object[])new String[] { "SEEN OR ANSWERED DELETED" });
/* 156 */     this.connection.search((Object[])new String[] { "OR DRAFT OR SEEN ANSWERED DELETED" });
/* 157 */     this.connection.search((Object[])new String[] { "OR HEADER Message-ID z@eg UNDELETED" });
/* 158 */     List<String> terms = Lists.newArrayList();
/* 159 */     terms.add("HEADER");
/* 160 */     terms.add("Message-ID");
/* 161 */     terms.add("a@eg.com");
/*     */     
/* 163 */     for (int cnt = 0; cnt < 3; cnt++) {
/* 164 */       terms.add(0, String.format("b%s@eg.com", new Object[] { Integer.valueOf(cnt) }));
/* 165 */       terms.add(0, "Message-ID");
/* 166 */       terms.add(0, "HEADER");
/* 167 */       terms.add(0, "OR");
/*     */     }
/* 169 */     terms.add("UNDELETED");
/* 170 */     this.connection.search(terms.toArray());
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testDeepNestedOrSearch() throws IOException, ServiceException {
/* 175 */     int maxNestingInSearchRequest = LC.imap_max_nesting_in_search_request.intValue();
/* 176 */     this.connection = connect();
/* 177 */     this.connection.select("INBOX");
/* 178 */     List<String> terms = Lists.newArrayList();
/* 179 */     terms.add("HEADER");
/* 180 */     terms.add("Message-ID");
/* 181 */     terms.add("a@eg.com");
/*     */     
/* 183 */     for (int cnt = 0; cnt < maxNestingInSearchRequest - 2; cnt++) {
/* 184 */       terms.add(0, String.format("b%s@eg.com", new Object[] { Integer.valueOf(cnt) }));
/* 185 */       terms.add(0, "Message-ID");
/* 186 */       terms.add(0, "HEADER");
/* 187 */       terms.add(0, "OR");
/*     */     }
/* 189 */     terms.add("UNDELETED");
/* 190 */     this.connection.search(terms.toArray());
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testTooDeepNestedOrSearch() throws IOException, ServiceException {
/* 195 */     int maxNestingInSearchRequest = LC.imap_max_nesting_in_search_request.intValue();
/* 196 */     this.connection = connect();
/* 197 */     this.connection.select("INBOX");
/* 198 */     List<String> terms = Lists.newArrayList();
/* 199 */     terms.add("HEADER");
/* 200 */     terms.add("Message-ID");
/* 201 */     terms.add("a@eg.com");
/*     */     
/* 203 */     for (int cnt = 0; cnt < maxNestingInSearchRequest; cnt++) {
/* 204 */       terms.add(0, String.format("b%s@eg.com", new Object[] { Integer.valueOf(cnt) }));
/* 205 */       terms.add(0, "Message-ID");
/* 206 */       terms.add(0, "HEADER");
/* 207 */       terms.add(0, "OR");
/*     */     }
/* 209 */     terms.add("UNDELETED");
/*     */     try {
/* 211 */       this.connection.search(terms.toArray());
/* 212 */       org.junit.Assert.fail("Expected search to fail due to complexity");
/*     */     } catch (CommandFailedException cfe) {
/* 214 */       String es = "parse error: Search query too complex";
/* 215 */       org.junit.Assert.assertTrue(String.format("Exception '%s' should contain string '%s'", new Object[] { cfe.getMessage(), es }), cfe.getMessage().contains(es));
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testDeepNestedAndSearch() throws IOException, ServiceException
/*     */   {
/* 222 */     int nesting = LC.imap_max_nesting_in_search_request.intValue() - 1;
/* 223 */     this.connection = connect();
/* 224 */     this.connection.select("INBOX");
/* 225 */     this.connection.search((Object[])new String[] { StringUtils.repeat("(", nesting) + "ANSWERED UNDELETED" + StringUtils.repeat(")", nesting) });
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testTooDeepNestedAndSearch()
/*     */     throws IOException, ServiceException
/*     */   {
/* 232 */     int nesting = LC.imap_max_nesting_in_search_request.intValue();
/* 233 */     this.connection = connect();
/* 234 */     this.connection.select("INBOX");
/*     */     try {
/* 236 */       this.connection.search((Object[])new String[] { StringUtils.repeat("(", nesting) + "ANSWERED UNDELETED" + StringUtils.repeat(")", nesting) });
/*     */       
/*     */ 
/* 239 */       org.junit.Assert.fail("Expected search to fail due to complexity");
/*     */     } catch (CommandFailedException cfe) {
/* 241 */       String es = "parse error: Search query too complex";
/* 242 */       org.junit.Assert.assertTrue(String.format("Exception '%s' should contain string '%s'", new Object[] { cfe.getMessage(), es }), cfe.getMessage().contains(es));
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */ 
/*     */   @Test
/*     */   public void testList93114DOSRegex()
/*     */     throws ServiceException, InterruptedException
/*     */   {
/* 253 */     StringBuilder regexPatt = new StringBuilder();
/* 254 */     for (int cnt = 1; cnt < 64; cnt++) {
/* 255 */       regexPatt.append(".*");
/*     */     }
/* 257 */     regexPatt.append(" HELLO");
/* 258 */     checkRegex(regexPatt.toString(), "EMAILED CONTACTS", Boolean.valueOf(false), 5000000, Boolean.valueOf(true));
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testList93114OkishRegex() throws ServiceException, InterruptedException {
/* 263 */     StringBuilder regexPatt = new StringBuilder();
/* 264 */     for (int cnt = 1; cnt < 10; cnt++) {
/* 265 */       regexPatt.append(".*");
/*     */     }
/* 267 */     regexPatt.append(" HELLO");
/*     */     
/* 269 */     checkRegex(regexPatt.toString(), "EMAILED CONTACTS", Boolean.valueOf(false), 10000000, Boolean.valueOf(false));
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testList93114StarRegex() throws ServiceException, InterruptedException {
/* 274 */     checkRegex(".*", "EMAILED CONTACTS", Boolean.valueOf(true), 1000, Boolean.valueOf(false));
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testList93114EndingACTSRegex() throws ServiceException, InterruptedException {
/* 279 */     checkRegex(".*ACTS", "EMAILED CONTACTS", Boolean.valueOf(true), 1000, Boolean.valueOf(false));
/* 280 */     checkRegex(".*ACTS", "INBOX", Boolean.valueOf(false), 1000, Boolean.valueOf(false));
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testList93114MatchingEmailedContactsRegex() throws ServiceException, InterruptedException {
/* 285 */     String target = "EMAILED CONTACTS";
/* 286 */     checkRegex(target, target, Boolean.valueOf(true), 1000, Boolean.valueOf(false));
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testList93114DosWithWildcards() throws Exception {
/*     */     try {
/* 292 */       List<ListData> listResult = this.connection.list("", "**************** HELLO");
/* 293 */       assertNotNull(listResult);
/*     */     } catch (CommandFailedException cfe) {
/* 295 */       ZimbraLog.test.info("Expected CommandFailedException", cfe);
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testList93114DosWithPercents() throws Exception {
/*     */     try {
/* 302 */       List<ListData> listResult = this.connection.list("", "%%%%%%%%%%%%%%%% HELLO");
/* 303 */       assertNotNull(listResult);
/*     */     } catch (CommandFailedException cfe) {
/* 305 */       ZimbraLog.test.info("Expected CommandFailedException", cfe);
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testList93114DosStarPercentRepeats() throws Exception {
/* 311 */     StringBuilder mboxPatt = new StringBuilder();
/* 312 */     for (int cnt = 1; cnt < 50; cnt++) {
/* 313 */       mboxPatt.append("*%");
/*     */     }
/* 315 */     mboxPatt.append(" HELLO");
/*     */     try {
/* 317 */       List<ListData> listResult = this.connection.list("", mboxPatt.toString());
/* 318 */       assertNotNull(listResult);
/*     */     } catch (CommandFailedException cfe) {
/* 320 */       ZimbraLog.test.info("Expected CommandFailedException", cfe);
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testListInbox() throws Exception {
/* 326 */     List<ListData> listResult = this.connection.list("", "INBOX");
/* 327 */     assertNotNull(listResult);
/* 328 */     assertEquals("List result should have this number of entries", 1, listResult.size());
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testListContacts() throws Exception {
/* 333 */     List<ListData> listResult = this.connection.list("", "*Contacts*");
/* 334 */     assertNotNull(listResult);
/*     */     
/* 336 */     assertTrue("List result should have at least 2 entries", listResult.size() >= 2);
/* 337 */     for (ListData le : listResult) {
/* 338 */       assertTrue(String.format("mailbox '%s' contains 'Contacts'", new Object[] { le.getMailbox() }), le.getMailbox().contains("Contacts"));
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testAppend() throws Exception
/*     */   {
/* 345 */     assertTrue(this.connection.hasCapability("UIDPLUS"));
/* 346 */     Flags flags = Flags.fromSpec("afs");
/* 347 */     Date date = new Date(System.currentTimeMillis());
/* 348 */     Literal msg = message(100000);
/*     */     try {
/* 350 */       AppendResult res = this.connection.append("INBOX", flags, date, msg);
/* 351 */       assertNotNull(res);
/* 352 */       byte[] b = fetchBody(res.getUid());
/* 353 */       org.junit.Assert.assertArrayEquals("content mismatch", msg.getBytes(), b);
/*     */     } finally {
/* 355 */       msg.dispose();
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testOverflowAppend() throws Exception {
/* 361 */     assertTrue(this.connection.hasCapability("UIDPLUS"));
/* 362 */     int oldReadTimeout = this.connection.getConfig().getReadTimeout();
/*     */     try {
/* 364 */       this.connection.setReadTimeout(10);
/* 365 */       Flags flags = Flags.fromSpec("afs");
/* 366 */       Date date = new Date(System.currentTimeMillis());
/* 367 */       ImapRequest req = this.connection.newRequest(CAtom.APPEND, new Object[] { new MailboxName("INBOX") });
/* 368 */       req.addParam("{2147483648+}");
/* 369 */       ImapResponse resp = req.send();
/* 370 */       assertTrue((resp.isNO()) || (resp.isBAD()));
/*     */       
/* 372 */       req = this.connection.newRequest(CAtom.APPEND, new Object[] { new MailboxName("INBOX") });
/* 373 */       req.addParam("{2147483648}");
/* 374 */       resp = req.send();
/* 375 */       assertTrue((resp.isNO()) || (resp.isBAD()));
/*     */     } finally {
/* 377 */       this.connection.setReadTimeout(oldReadTimeout);
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testOverflowNotAppend() throws Exception {
/* 383 */     int oldReadTimeout = this.connection.getConfig().getReadTimeout();
/*     */     try {
/* 385 */       this.connection.setReadTimeout(10);
/* 386 */       Flags flags = Flags.fromSpec("afs");
/* 387 */       Date date = new Date(System.currentTimeMillis());
/* 388 */       ImapRequest req = this.connection.newRequest(CAtom.FETCH, new Object[] { "1:*" });
/* 389 */       req.addParam("{2147483648+}");
/* 390 */       ImapResponse resp = req.send();
/* 391 */       assertTrue((resp.isNO()) || (resp.isBAD()));
/*     */     } finally {
/* 393 */       this.connection.setReadTimeout(oldReadTimeout);
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testAppendNoLiteralPlus() throws Exception {
/* 399 */     withLiteralPlus(false, new RunnableTest()
/*     */     {
/*     */       public void run() throws Exception {
/* 402 */         TestImap.this.testAppend();
/*     */       }
/*     */     });
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testStoreTags() throws Exception {
/* 409 */     ZMailbox mbox = TestUtil.getZMailbox("imap-test-user");
/* 410 */     List<ZTag> tags = mbox.getAllTags();
/* 411 */     assertTrue((tags == null) || (tags.size() == 0));
/*     */     
/* 413 */     String tagName = "T1";
/* 414 */     ZTag tag = mbox.getTag(tagName);
/* 415 */     if (tag == null) {
/* 416 */       tag = mbox.createTag(tagName, ZTag.Color.blue);
/*     */     }
/* 418 */     tags = mbox.getAllTags();
/* 419 */     assertTrue((tags != null) && (tags.size() == 1));
/* 420 */     assertEquals("T1", ((ZTag)tags.get(0)).getName());
/*     */     
/* 422 */     String folderName = "newfolder1";
/* 423 */     ZFolder folder = mbox.createFolder("1", folderName, ZFolder.View.message, ZFolder.Color.DEFAULTCOLOR, null, null);
/* 424 */     mbox.addMessage("2", "u", tag.getId(), System.currentTimeMillis(), simpleMessage("foo1"), true);
/* 425 */     mbox.addMessage("2", "u", "", System.currentTimeMillis(), simpleMessage("foo2"), true);
/*     */     
/* 427 */     MailboxInfo info = this.connection.select("INBOX");
/* 428 */     assertTrue("INBOX does not contain expected flag " + tagName, info.getFlags().isSet(tagName));
/*     */     
/* 430 */     Map<Long, MessageData> data = this.connection.fetch("1:*", "FLAGS");
/* 431 */     assertEquals(2, data.size());
/* 432 */     Iterator<Long> it = data.keySet().iterator();
/* 433 */     Long seq = (Long)it.next();
/* 434 */     assertTrue("flag not set on first message", ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/*     */     
/* 436 */     seq = (Long)it.next();
/* 437 */     assertFalse("flag unexpectedly set on second message", ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/*     */     
/* 439 */     this.connection.store(seq + "", "+FLAGS", tagName);
/* 440 */     data = this.connection.fetch(seq + "", "FLAGS");
/* 441 */     assertEquals(1, data.size());
/* 442 */     seq = (Long)data.keySet().iterator().next();
/* 443 */     assertTrue("flag not set after STORE in INBOX", ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/*     */     
/* 445 */     mbox.addMessage(folder.getId(), "u", "", System.currentTimeMillis(), simpleMessage("bar"), true);
/* 446 */     info = this.connection.select(folderName);
/* 447 */     assertFalse(folderName + " contains unexpected flag " + tagName, info.getFlags().isSet(tagName));
/*     */     
/* 449 */     data = this.connection.fetch("*", "FLAGS");
/* 450 */     assertEquals(1, data.size());
/* 451 */     seq = (Long)data.keySet().iterator().next();
/* 452 */     assertFalse("flag unexpectedly set on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/*     */     
/* 454 */     this.connection.store(seq + "", "+FLAGS", tagName);
/* 455 */     data = this.connection.fetch(seq + "", "FLAGS");
/* 456 */     assertEquals(1, data.size());
/* 457 */     seq = (Long)data.keySet().iterator().next();
/* 458 */     assertTrue("flag not set after STORE on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/*     */     
/* 460 */     info = this.connection.select(folderName);
/* 461 */     assertTrue("old tag not set in new folder", info.getFlags().isSet(tagName));
/*     */     
/* 463 */     String tagName2 = "T2";
/* 464 */     this.connection.store(seq + "", "+FLAGS", tagName2);
/* 465 */     data = this.connection.fetch(seq + "", "FLAGS");
/* 466 */     assertEquals(1, data.size());
/* 467 */     seq = (Long)data.keySet().iterator().next();
/* 468 */     assertTrue("flag not set after STORE on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/* 469 */     assertTrue("flag not set after STORE on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isSet(tagName2));
/*     */     
/* 471 */     info = this.connection.select(folderName);
/* 472 */     assertTrue("old tag not set in new folder", info.getFlags().isSet(tagName));
/* 473 */     assertTrue("new tag not set in new folder", info.getFlags().isSet(tagName2));
/*     */     
/* 475 */     tags = mbox.getAllTags();
/* 476 */     assertTrue((tags != null) && (tags.size() == 1));
/* 477 */     assertEquals("T1", ((ZTag)tags.get(0)).getName());
/*     */     
/* 479 */     String tagName3 = "T3";
/* 480 */     this.connection.store(seq + "", "FLAGS", tagName3);
/* 481 */     data = this.connection.fetch(seq + "", "FLAGS");
/* 482 */     assertEquals(1, data.size());
/* 483 */     seq = (Long)data.keySet().iterator().next();
/* 484 */     assertFalse("flag unexpectedly set after STORE on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/* 485 */     assertFalse("flag unexpectedly set after STORE on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isSet(tagName2));
/* 486 */     assertTrue("flag not set after STORE on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isSet(tagName3));
/*     */     
/* 488 */     info = this.connection.select(folderName);
/* 489 */     assertTrue("new tag not set in new folder", info.getFlags().isSet(tagName3));
/* 490 */     assertFalse("old tag unexpectedly set in new folder", info.getFlags().isSet(tagName));
/* 491 */     assertFalse("old tag unexpectedly set in new folder", info.getFlags().isSet(tagName2));
/*     */     
/* 493 */     tags = mbox.getAllTags();
/* 494 */     assertTrue((tags != null) && (tags.size() == 1));
/* 495 */     assertEquals("T1", ((ZTag)tags.get(0)).getName());
/*     */     
/*     */ 
/* 498 */     this.connection.store(seq + "", "-FLAGS", tagName3);
/* 499 */     data = this.connection.fetch(seq + "", "FLAGS");
/* 500 */     assertEquals(1, data.size());
/* 501 */     seq = (Long)data.keySet().iterator().next();
/* 502 */     assertTrue("flags unexpectedly set after STORE on message in " + folderName, ((MessageData)data.get(seq)).getFlags().isEmpty());
/*     */     
/* 504 */     info = this.connection.select("INBOX");
/* 505 */     assertTrue("old tag not set in new folder", info.getFlags().isSet(tagName));
/* 506 */     assertFalse("new tag unexpectedly set in new folder", info.getFlags().isSet(tagName2));
/*     */   }
/*     */   
/*     */   private void storeInvalidFlag(String flag, Long seq) throws IOException {
/*     */     try {
/* 511 */       this.connection.store(seq + "", "FLAGS", flag);
/* 512 */       fail("server allowed client to set system flag " + flag);
/*     */     }
/*     */     catch (CommandFailedException e) {}
/*     */     
/*     */ 
/* 517 */     Map<Long, MessageData> data = this.connection.fetch(seq + ":" + seq, "FLAGS");
/* 518 */     assertFalse(((MessageData)data.get(seq)).getFlags().isSet(flag));
/*     */     try {
/* 520 */       this.connection.store(seq + "", "+FLAGS", flag);
/* 521 */       fail("server allowed client to set system flag " + flag);
/*     */     }
/*     */     catch (CommandFailedException e) {}
/*     */     
/* 525 */     data = this.connection.fetch(seq + ":" + seq, "FLAGS");
/* 526 */     assertFalse(((MessageData)data.get(seq)).getFlags().isSet(flag));
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testStoreInvalidSystemFlag() throws Exception {
/* 531 */     ZMailbox mbox = TestUtil.getZMailbox("imap-test-user");
/* 532 */     mbox.addMessage("2", "u", "", System.currentTimeMillis(), simpleMessage("foo"), true);
/* 533 */     MailboxInfo info = this.connection.select("INBOX");
/* 534 */     Map<Long, MessageData> data = this.connection.fetch("1:*", "FLAGS");
/* 535 */     assertEquals(1, data.size());
/* 536 */     Iterator<Long> it = data.keySet().iterator();
/* 537 */     Long seq = (Long)it.next();
/*     */     
/* 539 */     storeInvalidFlag("\\Bulk", seq);
/* 540 */     storeInvalidFlag("\\Unread", seq);
/* 541 */     storeInvalidFlag("\\Forwarded", seq);
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testStoreTagsDirty() throws Exception {
/* 546 */     ZMailbox mbox = TestUtil.getZMailbox("imap-test-user");
/* 547 */     List<ZTag> tags = mbox.getAllTags();
/* 548 */     assertTrue((tags == null) || (tags.size() == 0));
/*     */     
/* 550 */     String tagName = "T1";
/* 551 */     String tagName2 = "T2";
/* 552 */     ZTag tag = mbox.getTag(tagName);
/* 553 */     if (tag == null) {
/* 554 */       tag = mbox.createTag(tagName, ZTag.Color.blue);
/*     */     }
/* 556 */     tags = mbox.getAllTags();
/* 557 */     assertTrue((tags != null) && (tags.size() == 1));
/* 558 */     assertEquals("T1", ((ZTag)tags.get(0)).getName());
/*     */     
/* 560 */     String folderName = "newfolder1";
/* 561 */     ZFolder folder = mbox.createFolder("1", folderName, ZFolder.View.message, ZFolder.Color.DEFAULTCOLOR, null, null);
/* 562 */     mbox.addMessage("2", "u", tag.getId(), System.currentTimeMillis(), simpleMessage("foo1"), true);
/*     */     
/* 564 */     MailboxInfo info = this.connection.select("INBOX");
/* 565 */     assertTrue("INBOX does not contain expected flag " + tagName, info.getFlags().isSet(tagName));
/* 566 */     assertFalse("INBOX contain unexpected flag T2", info.getFlags().isSet("T2"));
/*     */     
/* 568 */     Map<Long, MessageData> data = this.connection.fetch("1:*", "FLAGS");
/* 569 */     assertEquals(1, data.size());
/* 570 */     Iterator<Long> it = data.keySet().iterator();
/* 571 */     Long seq = (Long)it.next();
/* 572 */     assertTrue("flag not set on first message", ((MessageData)data.get(seq)).getFlags().isSet(tagName));
/*     */     
/* 574 */     ImapRequest req = this.connection.newRequest("STORE", new Object[] { seq + "", "+FLAGS", "T2" });
/* 575 */     req.setResponseHandler(new ResponseHandler()
/*     */     {
/*     */       public void handleResponse(ImapResponse res) throws Exception {
/* 578 */         if ((res.isUntagged()) && (res.getCCode() == CAtom.FLAGS)) {
/* 579 */           Flags flags = (Flags)res.getData();
/* 580 */           junit.framework.Assert.assertTrue(flags.isSet("T2"));
/*     */         }
/*     */       }
/* 583 */     });
/* 584 */     req.sendCheckStatus();
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testAppendTags() throws Exception {
/* 589 */     Flags flags = Flags.fromSpec("afs");
/* 590 */     String tag1 = "APPENDTAG1";
/* 591 */     flags.set(tag1);
/* 592 */     Date date = new Date(System.currentTimeMillis());
/* 593 */     Literal msg = message(10);
/*     */     try {
/* 595 */       AppendResult res = this.connection.append("INBOX", flags, date, msg);
/* 596 */       MessageData data = this.connection.uidFetch(res.getUid(), "FLAGS");
/* 597 */       assertTrue(data.getFlags().isSet(tag1));
/*     */     } finally {
/* 599 */       msg.dispose();
/*     */     }
/*     */     
/*     */ 
/* 603 */     ZMailbox mbox = TestUtil.getZMailbox("imap-test-user");
/* 604 */     List<ZTag> tags = mbox.getAllTags();
/* 605 */     assertTrue("APPEND created new visible tag", (tags == null) || (tags.size() == 0));
/*     */     
/*     */ 
/* 608 */     String tag2 = "APPENDTAG2";
/* 609 */     ZTag tag = mbox.getTag(tag2);
/* 610 */     if (tag == null) {
/* 611 */       tag = mbox.createTag(tag2, ZTag.Color.blue);
/*     */     }
/* 613 */     tags = mbox.getAllTags();
/* 614 */     assertTrue((tags != null) && (tags.size() == 1));
/* 615 */     assertEquals(tag2, ((ZTag)tags.get(0)).getName());
/*     */     
/* 617 */     mbox.addMessage("2", "u", tag.getId(), System.currentTimeMillis(), simpleMessage("foo1"), true);
/* 618 */     MailboxInfo info = this.connection.select("INBOX");
/* 619 */     assertTrue("INBOX does not contain expected flag " + tag2, info.getFlags().isSet(tag2));
/*     */     
/* 621 */     String folderName = "newfolder1";
/* 622 */     ZFolder folder = mbox.createFolder("1", folderName, ZFolder.View.message, ZFolder.Color.DEFAULTCOLOR, null, null);
/*     */     
/* 624 */     info = this.connection.select(folderName);
/* 625 */     assertFalse("new tag unexpectedly set in new folder", info.getFlags().isSet(tag2));
/*     */     
/* 627 */     msg = message(10);
/* 628 */     flags = Flags.fromSpec("afs");
/* 629 */     flags.set(tag2);
/*     */     try {
/* 631 */       AppendResult res = this.connection.append(folderName, flags, date, msg);
/* 632 */       MessageData data = this.connection.uidFetch(res.getUid(), "FLAGS");
/* 633 */       assertTrue(data.getFlags().isSet(tag2));
/*     */     } finally {
/* 635 */       msg.dispose();
/*     */     }
/*     */     
/* 638 */     info = this.connection.select(folderName);
/* 639 */     assertTrue("new tag not set in new folder", info.getFlags().isSet(tag2));
/*     */   }
/*     */   
/*     */   private void appendInvalidFlag(String flag) throws IOException {
/* 643 */     Literal msg = message(10);
/* 644 */     Flags flags = Flags.fromSpec("afs");
/* 645 */     flags.set(flag);
/* 646 */     Date date = new Date(System.currentTimeMillis());
/*     */     try {
/* 648 */       AppendResult res = this.connection.append("INBOX", flags, date, msg);
/* 649 */       fail("server allowed client to set system flag " + flag);
/*     */     }
/*     */     catch (CommandFailedException e) {}finally
/*     */     {
/* 653 */       msg.dispose();
/*     */     }
/* 655 */     this.connection.noop();
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testAppendInvalidSystemFlag() throws Exception
/*     */   {
/* 661 */     appendInvalidFlag("\\Bulk");
/* 662 */     appendInvalidFlag("\\Unread");
/* 663 */     appendInvalidFlag("\\Forwarded");
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testAppendTagsDirty() throws Exception {
/* 668 */     Flags flags = Flags.fromSpec("afs");
/* 669 */     String tag1 = "NEWDIRTYTAG";
/* 670 */     MailboxInfo info = this.connection.select("INBOX");
/* 671 */     assertFalse("INBOX contains unexpected flag NEWDIRTYTAG", info.getFlags().isSet("NEWDIRTYTAG"));
/*     */     
/* 673 */     flags.set("NEWDIRTYTAG");
/* 674 */     Date date = new Date(System.currentTimeMillis());
/* 675 */     Literal msg = message(10);
/*     */     try {
/* 677 */       ImapRequest req = this.connection.newRequest("APPEND", new Object[] { "INBOX", flags, date, msg });
/* 678 */       req.setResponseHandler(new ResponseHandler()
/*     */       {
/*     */         public void handleResponse(ImapResponse res) throws Exception {
/* 681 */           if ((res.isUntagged()) && (res.getCCode() == CAtom.FLAGS)) {
/* 682 */             Flags flags = (Flags)res.getData();
/* 683 */             junit.framework.Assert.assertTrue(flags.isSet("NEWDIRTYTAG"));
/*     */           }
/*     */         }
/* 686 */       });
/* 687 */       req.sendCheckStatus();
/*     */     } finally {
/* 689 */       msg.dispose();
/*     */     }
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testCatenateSimple() throws Exception
/*     */   {
/* 696 */     assertTrue(this.connection.hasCapability("CATENATE"));
/* 697 */     assertTrue(this.connection.hasCapability("UIDPLUS"));
/* 698 */     String part1 = simpleMessage("test message");
/* 699 */     String part2 = "more text\r\n";
/* 700 */     AppendMessage am = new AppendMessage(null, null, new Object[] { literal(part1), literal(part2) });
/*     */     
/* 702 */     AppendResult res = this.connection.append("INBOX", new AppendMessage[] { am });
/* 703 */     this.connection.select("INBOX");
/* 704 */     byte[] body = fetchBody(res.getUid());
/* 705 */     org.junit.Assert.assertArrayEquals("content mismatch", bytes(part1 + part2), body);
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testCatenateSimpleNoLiteralPlus() throws Exception
/*     */   {
/* 711 */     withLiteralPlus(false, new RunnableTest()
/*     */     {
/*     */       public void run() throws Exception {
/* 714 */         TestImap.this.testCatenateSimple();
/*     */       }
/*     */     });
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testCatenateUrl() throws Exception {
/* 721 */     assertTrue(this.connection.hasCapability("CATENATE"));
/* 722 */     assertTrue(this.connection.hasCapability("UIDPLUS"));
/* 723 */     String msg1 = simpleMessage("test message");
/* 724 */     AppendResult res1 = this.connection.append("INBOX", null, null, literal(msg1));
/* 725 */     String s1 = "first part\r\n";
/* 726 */     String s2 = "second part\r\n";
/* 727 */     String msg2 = msg1 + s1 + s2;
/* 728 */     AppendMessage am = new AppendMessage(null, null, new Object[] { url("INBOX", res1), literal(s1), literal(s2) });
/*     */     
/* 730 */     AppendResult res2 = this.connection.append("INBOX", new AppendMessage[] { am });
/* 731 */     this.connection.select("INBOX");
/* 732 */     byte[] b2 = fetchBody(res2.getUid());
/* 733 */     org.junit.Assert.assertArrayEquals("content mismatch", bytes(msg2), b2);
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testMultiappend() throws Exception {
/* 738 */     assertTrue(this.connection.hasCapability("MULTIAPPEND"));
/* 739 */     assertTrue(this.connection.hasCapability("UIDPLUS"));
/* 740 */     AppendMessage msg1 = new AppendMessage(null, null, new Object[] { literal("test 1") });
/* 741 */     AppendMessage msg2 = new AppendMessage(null, null, new Object[] { literal("test 2") });
/* 742 */     AppendResult res = this.connection.append("INBOX", new AppendMessage[] { msg1, msg2 });
/* 743 */     assertNotNull(res);
/* 744 */     assertEquals("expecting 2 uids", 2, res.getUids().length);
/*     */   }
/*     */   
/*     */   @Test
/*     */   public void testMultiappendNoLiteralPlus() throws Exception {
/* 749 */     withLiteralPlus(false, new RunnableTest()
/*     */     {
/*     */       public void run() throws Exception {
/* 752 */         TestImap.this.testMultiappend();
/*     */       }
/*     */     });
/*     */   }
/*     */   
/*     */   private String url(String mbox, AppendResult res) {
/* 758 */     return String.format("/%s;UIDVALIDITY=%d/;UID=%d", new Object[] { mbox, Long.valueOf(res.getUidValidity()), Long.valueOf(res.getUid()) });
/*     */   }
/*     */   
/*     */   private static Literal literal(String s)
/*     */   {
/* 763 */     return new Literal(bytes(s));
/*     */   }
/*     */   
/*     */   private static byte[] bytes(String s) {
/*     */     try {
/* 768 */       return s.getBytes("UTF8");
/*     */     } catch (UnsupportedEncodingException e) {
/* 770 */       fail("UTF8 encoding not supported");
/*     */     }
/* 772 */     return null;
/*     */   }
/*     */   
/*     */   private byte[] fetchBody(long uid) throws IOException {
/* 776 */     MessageData md = this.connection.uidFetch(uid, "(BODY.PEEK[])");
/* 777 */     assertNotNull("message not found", md);
/* 778 */     assertEquals(uid, md.getUid());
/* 779 */     Body[] bs = md.getBodySections();
/* 780 */     assertNotNull(bs);
/* 781 */     assertEquals(1, bs.length);
/* 782 */     return bs[0].getImapData().getBytes();
/*     */   }
/*     */   
/*     */   private static Literal message(int size) throws IOException {
/* 786 */     File file = File.createTempFile("msg", null);
/* 787 */     file.deleteOnExit();
/* 788 */     FileWriter out = new FileWriter(file);
/*     */     try {
/* 790 */       out.write(simpleMessage("test message"));
/* 791 */       for (int i = 0; i < size; i++) {
/* 792 */         out.write(88);
/* 793 */         if (i % 72 == 0) {
/* 794 */           out.write("\r\n");
/*     */         }
/*     */       }
/*     */     } finally {
/* 798 */       out.close();
/*     */     }
/* 800 */     return new Literal(file, true);
/*     */   }
/*     */   
/*     */   private static String simpleMessage(String text) {
/* 804 */     return "Return-Path: dac@zimbra.com\r\nDate: Fri, 27 Feb 2004 15:24:43 -0800 (PST)\r\nFrom: dac <dac@zimbra.com>\r\nTo: bozo <bozo@foo.com>\r\nSubject: Foo foo\r\n\r\n" + text + "\r\n";
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private void withLiteralPlus(boolean lp, RunnableTest test)
/*     */     throws Exception
/*     */   {
/* 812 */     ImapConfig config = this.connection.getImapConfig();
/* 813 */     boolean oldLp = config.isUseLiteralPlus();
/* 814 */     config.setUseLiteralPlus(lp);
/*     */     try {
/* 816 */       test.run();
/*     */     } finally {
/* 818 */       config.setUseLiteralPlus(oldLp);
/*     */     }
/*     */   }
/*     */   
/*     */ 
/*     */ 
/*     */   private ImapConnection connect()
/*     */     throws IOException
/*     */   {
/* 827 */     ImapConfig config = new ImapConfig("localhost");
/* 828 */     config.setPort(7143);
/* 829 */     config.setAuthenticationId("imap-test-user");
/* 830 */     config.getLogger().setLevel(Log.Level.trace);
/* 831 */     ImapConnection connection = new ImapConnection(config);
/* 832 */     connection.connect();
/* 833 */     connection.login("test123");
/* 834 */     connection.select("INBOX");
/* 835 */     return connection;
/*     */   }
/*     */   
/*     */   public static void amain(String[] args) throws Exception {
/* 839 */     TestUtil.cliSetup();
/* 840 */     TestUtil.runTest(TestImapImport.class);
/*     */   }
/*     */   
/*     */   private static abstract interface RunnableTest
/*     */   {
/*     */     public abstract void run()
/*     */       throws Exception;
/*     */   }
/*     */ }


/* Location:              /home/mint/zimbrastore.jar!/com/zimbra/qa/unittest/TestImap.class
 * Java compiler version: 7 (51.0)
 * JD-Core Version:       0.7.1
 */